#!/usr/bin/env python

# obtain a run-time snapshot of version details for the script, python-env, OS, and OpenGL
# e.g., for saving into a data-file

from psychopy import core, visual
import os, sys, platform, time

import subprocess, shlex  # for shellCall()

__author__ = 'Jeremy R. Gray, jrgray@gmail.com'
    
def shellCall(shellCmd, retStdErr=False):
    """Calls a shell command, returns the stdout from the command.
    
    Return stderr if retStdErr==True; ignore shell return code
    """  
    
    stdoutData, stderrData = subprocess.Popen(shlex.split(shellCmd),stdout=subprocess.PIPE).communicate()
    if retStdErr:
        return stdoutData.strip(), stderrData.strip()
    else:
        return stdoutData.strip()

def runtimeProfile(scriptAuthor='', verbose=False, dict=False):
    """Returns run-time info about the script, python-env, system, and openGL.
    
    Returns a multi-line string suitable for printing to a log file (by default), or
    can return a python dictionary (kwarg dict=True).
    Takes scriptAuthor argument (= author of your script or experiment, not author of psychopy)
    Can be told to report more detail (including OpenGL stuff) with verbose=True
    Tries to discover the svn revision number of the directory containing the calling script (non-windows).
    """
    
    profileHeader =  'runtimeProfile = '
    profileInfo = '{ # -----------\n'
    
    import psychopy
    profileInfo += '  #PsychoPy:\n'
    profileInfo += '    "psychopyVersion": "'+psychopy.__version__+'",   # see http://www.psychopy.org\n'
    
    profileInfo += '  #Script:\n'
    profileInfo += '    "scriptName": "'+os.path.basename(sys.argv[0])+'",\n'
    if len(scriptAuthor):
        profileInfo += '    "scriptAuthor": "'+scriptAuthor+'",\n'
    profileInfo += '    "scriptRunDate": "'+time.ctime()+'",\n'
    scriptDir = os.path.dirname(os.path.abspath(sys.argv[0]))
    profileInfo += '    "scriptFullPath": "'+scriptDir+'",\n'
    
    # script under version control? look for svn revision number:
    try:
        if core.sys.platform == 'darwin' or core.sys.platform == 'linux':
            svnrev = shellCall('svnversion -n "'+scriptDir+'"')
        else:
            raise
            """ if you are using Windows and TortoiseSVN, maybe something along these lines could be made to work??
            f = open('tmp.in')
            f.write('$WCREV$')
            f.close()
            shellCall('subwcrev.exe path tmp.in tmp.h')
            f = open('tmp.h')
            svnrev = f.readln()
            f.close()
            os.unlink('tmp.in', 'tmp.h')"""
        if svnrev != 'exported': # exported means you have svn, but this directory is not under version control
            svnrev = 'r'+svnrev
        profileInfo += '    "scriptSVNrevision": "'+svnrev+'",   # from svnversion scriptFullPath\n'
    except:
        pass
    
    profileInfo += '  #System:\n'
    profileInfo += '    "hostname": "'+platform.node()+'",\n'
    profileInfo += '    "platform": "'+core.sys.platform
    if core.sys.platform=='darwin':
        OSXver, junk, architecture = platform.mac_ver()
        profileInfo += ' '+OSXver+' '+architecture+'",\n'
    else:
        profileInfo += ',\n'
    profileInfo += '    "python_Version": "'+core.sys.version.split()[0]+'",\n'
    
    if verbose:
        # External packages:
        import numpy; profileInfo += '    "numpy_Version": "'+numpy.__version__+'",\n'
        import scipy; profileInfo += '    "scipy_Version": "'+scipy.__version__+'",\n'
        import matplotlib; profileInfo += '    "matplotlib_Version": "'+matplotlib.__version__+'",\n'
        import pyglet; profileInfo += '    "pyglet_Version": "'+pyglet.__version__+'",\n'
        try:
            import pygame; profileInfo += '    "pygame_Version": "'+pygame.__version__+'",\n'
        except:
            pass
        
        # Python gory details:
        profileInfo += '    "pythonFullVersion": "'+sys.version.replace('\n',' ')+'",\n'
        profileInfo += '    "pythonExecutable": "'+sys.executable+'",\n'
        
        # OpenGL info:
        profileInfo += '  #OpenGL:\n'
        tmpwin = visual.Window([10,10]) # some drivers want a window open first
        from pyglet.gl import gl_info
        profileInfo += '    "openGL_vendor": "'+gl_info.get_vendor()+'",\n'
        profileInfo += '    "openGL_renderingEngine": "'+gl_info.get_renderer()+'",\n'
        profileInfo += '    "openGL_version": "'+gl_info.get_version()+'",\n'
        
        extensionsOfInterest=['GL_ARB_multitexture', 
            'GL_EXT_framebuffer_object','GL_ARB_fragment_program',
            'GL_ARB_shader_objects','GL_ARB_vertex_shader',
            'GL_ARB_texture_non_power_of_two','GL_ARB_texture_float']
        for ext in extensionsOfInterest:
            profileInfo += '    "'+ext+'": '+str(bool(gl_info.have_extension(ext)))+',\n'
        tmpwin.close()
    
    profileInfo += '} # ----------------------------\n'
    if dict:
        return eval(profileInfo)
    return profileHeader + profileInfo


if __name__ == '__main__':
    rtp = runtimeProfile(scriptAuthor=__author__)
    print rtp.replace('"','')
    
    print runtimeProfile(dict=True, verbose=True)
    
     
    